#define PUDGE_META_VISITOR_SPEC BOOST_PP_ITERATION()

template<BOOST_PP_ENUM_PARAMS(PUDGE_META_VISITOR_SPEC, class T)>
struct visitor<BOOST_PP_ENUM_PARAMS(PUDGE_META_VISITOR_SPEC, T)>
{
	typedef visitor<BOOST_PP_ENUM_PARAMS(PUDGE_META_VISITOR_SPEC, T)> self_type;

	virtual ~visitor() {}

#define PUDGE_META_VISITOR_M(Z,N,A) virtual void visit(T ## N & t) { }
	BOOST_PP_REPEAT(PUDGE_META_VISITOR_SPEC, PUDGE_META_VISITOR_M, );
#undef PUDGE_META_VISITOR_M

	template<class Function> struct function : self_type
	{
		typedef Function function_type;
		typedef self_type visitor_type;
		Function & function_;
		function(Function & function__) : function_(function__){}
		virtual ~function() {}

#define PUDGE_META_VISITOR_M(Z,N,A) virtual void visit(T ## N & t) { function_(t); }
		BOOST_PP_REPEAT(PUDGE_META_VISITOR_SPEC, PUDGE_META_VISITOR_M, );
#undef PUDGE_META_VISITOR_M
	};

	struct client
	{
		typedef self_type visitor_type;
		virtual ~client(){}
		virtual void accept(visitor_type & visitor_) = 0;
		template<class Visitor> void operator()(Visitor & visitor_)
		{
			accept(self_type::function<Visitor>(visitor_));
		}
	};
	template<class T> struct clientd : client
	{
		virtual ~clientd() {}
		virtual void accept(visitor_type & visitor_)
		{
			visitor_.visit(*static_cast<T*>(this));
		}
	};
	template<class T> struct clientr : client
	{
		T & value;
		clientr(T & t) : value(t) {}
		virtual ~clientr() {}
		virtual void accept(visitor_type & visitor_)
		{
			visitor_.visit(value);
		}
	};
	template<class T> struct clientv : client
	{
		T value;
		clientv(T & t) : value(t) {}
		virtual ~clientv() {}
		virtual void accept(visitor_type & visitor_)
		{
			visitor_.visit(value);
		}
	};
};
